package cn.keniykey.mc.landterritory.land;

import java.util.HashMap;
import java.util.UUID;

import javax.annotation.Nullable;

import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import cn.keniykey.mc.landterritory.LandTerritoryMain;
import cn.keniykey.mc.landterritory.config.ConfigurationManager;
import cn.keniykey.mc.landterritory.config.LanguageManager;
import cn.keniykey.mc.landterritory.event.LandCreateEvent;
import cn.keniykey.mc.landterritory.event.LandTerritoryReloadConfigEvent;
import cn.keniykey.mc.landterritory.land.api.LandPoint;
import cn.keniykey.mc.landterritory.land.api.LandRange;
import cn.keniykey.mc.landterritory.landview.LandViewUtil;
import cn.keniykey.mc.landterritory.toolkit.TimeUtil;
import cn.keniykey.mc.landterritory.toolkit.Util;

public final class LandRangeToolListener implements Listener{
	
	private static final NamespacedKey NBTKEY_LANDTOOL;
	private static boolean USE_NBT = true;
	private static LandRangeToolListener lis;
	
	static {
		NBTKEY_LANDTOOL = new NamespacedKey(LandTerritoryMain.getPlugin(), "landrange_tool");
	}
	public static void putLandRange(Player player,@Nullable LandRange range) {
		final UUID player_uuid = player.getUniqueId();
		if(range == null) {
			lis.hashmap_players_range.remove(player_uuid);
		}else {
			lis.hashmap_players_range.put(player_uuid, range);
		}
	}
	@Nullable
	public static LandRange getLandRange(Player player) {
		final UUID player_uuid = player.getUniqueId();
		return (lis.hashmap_players_range.containsKey(player_uuid) ? lis.hashmap_players_range.get(player_uuid) : null);
	}
	public static ItemStack getLandRangeTool() {
		final ItemStack item = new ItemStack(ConfigurationManager.View_LandCreate_Tool_Item);
		final ItemMeta meta = item.getItemMeta();
		meta.setDisplayName(LanguageManager.getLang(1104100));
		meta.setLore(Util.listFromStr(LanguageManager.getLang(1104101, TimeUtil.getTimeStr(0l, 
				LanguageManager.getLang(1104102)))));
		if(USE_NBT) {
			try {
				meta.getPersistentDataContainer().set(NBTKEY_LANDTOOL,
						org.bukkit.persistence.PersistentDataType.BYTE,(byte)0);
			}catch(Exception ex) {
				ex.printStackTrace();
				USE_NBT = false;
			}
		}
		item.setItemMeta(meta);
		return item;
	}
	
	private final HashMap<UUID,LandRange> hashmap_players_range = new HashMap<>();
	private String str_landtool_name;
	
	public LandRangeToolListener() {
		lis = this;
		try {
			Class.forName("org.bukkit.persistence.PersistentDataAdapterContext");
			USE_NBT = true;
		}catch(Exception ex) {
			USE_NBT = false;
		}
	}
	
	@EventHandler
	public void onLandConfigReload(final LandTerritoryReloadConfigEvent e) {
		this.str_landtool_name = null;
	}
	@EventHandler(priority = EventPriority.MONITOR)
	public void onLandCreate(final LandCreateEvent e) {
		this.hashmap_players_range.remove(e.getPlayer().getUniqueId());
	}
	@EventHandler(priority = EventPriority.MONITOR)
	public void onPlayerQuit(final PlayerQuitEvent e) {
		this.hashmap_players_range.remove(e.getPlayer().getUniqueId());
	}
	@EventHandler(priority = EventPriority.MONITOR,ignoreCancelled = true)
	public void onPlayerTeleport(final PlayerTeleportEvent e) {
		if(e.getFrom().getWorld().getName().endsWith(e.getTo().getWorld().getName())) return;
		final UUID player_uuid = e.getPlayer().getUniqueId();
		if(this.hashmap_players_range.remove(player_uuid) == null) return;
		e.getPlayer().sendMessage(LanguageManager.getChatLang(1006101));
	}
	@EventHandler(priority = EventPriority.LOW)
	public void onPlayerInteract(final PlayerInteractEvent e) {
		if(e.getHand() == null || !EquipmentSlot.HAND.equals(e.getHand())) return;
		if(!e.hasItem()) return;
		switch(e.getAction()) {
		case LEFT_CLICK_BLOCK:
		case RIGHT_CLICK_BLOCK:
			break;
		default:
			return;
		}
		final ItemStack item_player = e.getItem();
		if(item_player == null || !item_player.getType().equals(ConfigurationManager.View_LandCreate_Tool_Item)) return;
		final ItemMeta meta = item_player.getItemMeta();
		if(!meta.hasLore() || !meta.hasDisplayName()) return;
		if(USE_NBT) {//针对低版本适配，如果出现NBT无法使用，则不使用NBT直接判断物品名
			try {
				org.bukkit.persistence.PersistentDataContainer container = meta.getPersistentDataContainer();
				if(!container.has(NBTKEY_LANDTOOL, org.bukkit.persistence.PersistentDataType.BYTE)) return;
			}catch(Exception ex) {
				ex.printStackTrace();
				USE_NBT = false;
			}
		}
		if(!USE_NBT) {
			if(this.str_landtool_name == null) this.str_landtool_name = LanguageManager.getLang(1104100);
			if(!this.str_landtool_name.equals(meta.getDisplayName())) return;
		}
		e.setCancelled(true);
		switch(e.getAction()) {
		case LEFT_CLICK_BLOCK:
			this.selectLandRange(e.getPlayer(), new LandPoint(e.getClickedBlock().getLocation()), null);
			break;
		case RIGHT_CLICK_BLOCK:
			this.selectLandRange(e.getPlayer(), null, new LandPoint(e.getClickedBlock().getLocation()));
			break;
		default:
		}
	}
	private void selectLandRange(Player player,@Nullable LandPoint point1,@Nullable LandPoint point2) {
		final UUID player_uuid = player.getUniqueId();
		if(point1 == null && point2 == null) {
			this.hashmap_players_range.remove(player_uuid);
			return;
		}
		final LandRange range;
		if(this.hashmap_players_range.containsKey(player_uuid)) {
			range = this.hashmap_players_range.get(player_uuid);
		}else {
			range = new LandRange();
			this.hashmap_players_range.put(player_uuid, range);
		}
		if(point1 != null) {//设置点1
			if(range.getLandPointTwo() != null && !range.getLandPointTwo().getWorldName().equals(point1.getWorldName())) {
				player.sendMessage(LanguageManager.getChatLang(1006100));
			}else {
				range.setLandPointOne(point1);
			}
		}
		if(point2 != null) {//设置点2
			if(range.getLandPointOne() != null && !range.getLandPointOne().getWorldName().equals(point2.getWorldName())) {
				player.sendMessage(LanguageManager.getChatLang(1006100));
			}else {
				range.setLandPointTwo(point2);
			}
		}
		player.sendMessage(LanguageManager.getLang(1006000));
		player.sendMessage(LandViewUtil.getLandRangeListStr(range));
		if(range.isRangeAllow()) player.sendMessage(LanguageManager.getLang(1006002));
	}
}